"""
Copyright (c) 2022 Huawei Technologies Co.,Ltd.

openGauss is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:

          http://license.coscl.org.cn/MulanPSL2

THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
"""
"""
Case Type   : 故障&可靠性测试
Case Name   : 主节点故障	临时表操作过程中dn主故障
Create At   : 2020/07/02
@zou_jialiang0505328114
Description :
    1.执行tpcc
    2.在执行tpcc期间，移除gaussdb，kill主进程
    3.查询数据库状态
    4.恢复数据库目录
    5.备库切换至主库
    6.查看数据库状态
    7.备库重建
    8.查看数据库状态
    9.主备切换
    10.恢复环境
Expect      :
    1.开始执行tpcc成功
    2.移除gaussdb成功，kill主进程成功
    3.查询数据库状态异常
    4.恢复数据库目录成功
    5.备库切换至主库成功
    6.查看数据库状态Primary Normal
    7.备库重建成功
    8.查看数据库状态正常
    9.主备切换成功
    10.恢复环境成功
History     :
    modified ：2020-12-4 by @peilinqian ；kill_pid方法会导致tpcc进程也被被kill，
    该用例只需要kill数据库进程，修改kill数据库进程方法；switchover去掉-w参数，等待返回成功信息；
    modified ：2022-03-03 by @wan005 ；优化故障恢复，优化步骤
"""

import os
import time
import unittest
from yat.test import Node
from yat.test import macro

from testcase.utils.Logger import Logger
from testcase.utils.Constant import Constant
from testcase.utils.Common import Common
from testcase.utils.CommonSH import CommonSH
from testcase.utils.CommonSH import RestartDbCluster
from testcase.utils.ComThread import ComThread


class IndexFileDamaged(unittest.TestCase):
    sh_primy = CommonSH('PrimaryDbUser')
    sh_standby = CommonSH('Standby1DbUser')
    sh_standby2 = CommonSH('Standby2DbUser')
    nodes_tuple = ('PrimaryDbUser', 'Standby1DbUser', 'Standby2DbUser')

    @RestartDbCluster(*nodes_tuple)
    def setUp(self):
        self.log = Logger()
        self.log.info(f'-----{os.path.basename(__file__)} start-----')
        self.dbPrimaryDbUser = Node(node='PrimaryDbUser')
        self.dbPrimaryRoot = Node(node='PrimaryRoot')
        self.dbStandby1Root = Node(node='Standby1Root')
        self.dbStandby1DbUser = Node(node='Standby1DbUser')
        self.com = Common()
        self.Constant = Constant()

    def test_abc(self):
        self.log.info('-----step1:start TPCC;expect:开启成功-----')
        tpcc_thread = ComThread(self.com.startTPCC,
                                args=(self.dbPrimaryRoot, macro.TPCC_PATH,))
        tpcc_thread.setDaemon(True)
        tpcc_thread.start()

        time.sleep(5)

        try:
            self.log.info("-----step2.1:移除dn1目录kill主进程;epxect:成功-----")
            mvcmd = f"mv {macro.DB_INSTANCE_PATH} " \
                    f"{macro.DB_INSTANCE_PATH + '.baktest'} "
            self.log.info(mvcmd)
            result = self.dbPrimaryRoot.sh(mvcmd).result()
            self.log.info(result)
            self.assertEqual('', result)

            self.log.info('kill主进程')
            self.com.kill_pid_keyword('gaussdb', 9, self.dbPrimaryDbUser)
            time.sleep(1)

            # 无需判断tpcc结果
            tpcc_thread.join(int(macro.TPCC_RUN_MAX_TIME) * 2)
            tpcc_result = tpcc_thread.get_result()
            self.log.info(tpcc_result)

            self.log.info('-----step3:备机查询数据库状态;epxect:异常-----')
            status = self.sh_standby.getDbClusterStatus("status")
            self.log.info(status)
            self.assertFalse(status)

            self.log.info('-----step4:恢复数据库目录;epxect:成功-----')
            mvcmd1 = f"mv {macro.DB_INSTANCE_PATH + '.baktest'} " \
                     f"{macro.DB_INSTANCE_PATH}"
            self.log.info(mvcmd1)
            result = self.dbPrimaryRoot.sh(mvcmd1).result()
            self.log.info(result)
            self.assertEqual('', result)

            self.log.info('-----step5:备库切换至主库;epxect:成功-----')
            switch_msg = self.sh_standby.executeGsctl('failover',
                                                      self.Constant.
                                                      FAILOVER_SUCCESS_MSG,
                                                      '', False)
            self.log.info(switch_msg)
            self.assertTrue(switch_msg)
            refreshMsg = self.sh_standby.exec_refresh_conf()
            self.log.info(refreshMsg)
            self.assertTrue(refreshMsg)
            time.sleep(60)

            self.log.info('-----step6:查看数据库状态;epxect:Primary Normal-----')
            status = self.sh_primy.getDbClusterStatus("detail")
            self.log.info(status)
            self.assertIn(self.Constant.PRIMARY_NORMAL, status)

            self.log.info('-----step7:备库重建;epxect:成功-----')
            rebuild_msg = self.sh_primy.executeGsctl('build',
                                                     self.Constant.
                                                     REBUILD_SUCCESS_MSG,
                                                     '-b full')
            self.log.info(rebuild_msg)
            self.assertTrue(rebuild_msg)

            self.log.info('--step8:查看数据库状态;epxect:成功-----')
            status = self.sh_primy.getDbClusterStatus("detail")
            self.log.info(status)

            self.log.info('--step9:主备切换;epxect:成功-----')
            switch_msg = self.sh_primy.executeGsctl('switchover',
                                                    self.Constant.
                                                    SWITCH_SUCCESS_MSG,
                                                    '-m fast')
            self.log.info(switch_msg)
            self.assertTrue(switch_msg)
            refreshMsg = self.sh_primy.exec_refresh_conf()
            self.log.info(refreshMsg)
            self.assertTrue(refreshMsg)
        finally:
            self.log.info("-----恢复dn1目录-----")
            mvcmd = f"mv {macro.DB_INSTANCE_PATH + '.baktest'} " \
                    f"{macro.DB_INSTANCE_PATH}"
            self.dbPrimaryRoot.sh(mvcmd)
            self.log.info(mvcmd)

    def tearDown(self):
        self.log.info('-----this is tearDown-----')
        self.log.info('-----step10:恢复主备关系;epxect:成功-----')
        host_name = self.dbPrimaryRoot.sh('hostname').result()
        if self.sh_primy.check_whether_need_switch(host_name):
            is_switched = self.sh_primy.executeGsctl('switchover',
                                                     self.Constant.
                                                     SWITCH_SUCCESS_MSG)
            self.log.info(is_switched)
            refreshMsg = self.sh_primy.exec_refresh_conf()
            self.log.info(refreshMsg)
            self.assertTrue(refreshMsg)
        status = self.sh_primy.getDbClusterStatus("detail")
        self.log.info(status)
        self.assertTrue(status)
        self.log.info(f'-----{os.path.basename(__file__)}:用例执行完毕-----')
